#region Licence
// Copyright (c) 2008 Tasman Logic Ltd

// Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
// and associated documentation files (the "Software"), to deal in the Software without restriction, 
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all copies 
// or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endregion

using System;
using System.Reflection;
using ActiveSharp.Utils;

namespace ActiveSharp.PropertyMapping
{
    /// <summary>
    /// The primary API for getting information about which properties have changed.  In fact, you can 
    /// use ONLY this class, if you like.  (The other classes, which it calls, are only public for 
    /// users with special requirements, who may need to call them directly.)
    /// </summary>
    /// <remarks>If you are doing property change notification, you may like to use <see cref="PropertyChangeHelper"/> instead.
    /// If you want faster performance, and don't mind a _little_ more RAM usage, then use <see cref="FastPropertyMap"/> instead</remarks>
    public static class PropertyMap
    {
        /// <summary>
        /// Returns the property which corresponds to the given field.
        /// </summary>
        /// <param name="containingObject">The object that the field belongs to</param>
        /// <param name="field">The field, passed by ref.  (This routine will never change the value, it simply
        /// needs the field to be passed by ref in order to work it's "magic"</param>
        /// <returns>A <see cref="PropertyInfo"/> for the property that sets the field</returns>
        public static PropertyInfo GetProperty<T>(object containingObject, ref T field)
        {
            PropertyMapForType mapForType = _propertyMaps[containingObject.GetType()];
            return mapForType.GetProperty(containingObject, ref field);
        }

        static LazyDictionaryOfTypes<PropertyMapForType> _propertyMaps = new LazyDictionaryOfTypes<PropertyMapForType>(
            delegate(Type t)
            {
                return new PropertyMapForType(t);
            });
    }

}
